/*************************************************************************
	> File Name: test.cpp
	> Author: zq
	> Mail: zhouquan1511@163.com 
	> Created Time: Wed 26 Apr 2023 08:50:24 PM CST
 ************************************************************************/
#include "Common.h"
#include "ConcurrentAlloc.h"

void test() {
	cout << "hello tcmalloc" << endl;
}

struct TreeNode {
	int _val;
	TreeNode *_left;
	TreeNode *_right;
	TreeNode()
		:_val(0)
		,_left(nullptr)
		,_right(nullptr)
	{}
};

//测试定长内存池
void TestObjectPool()
{
	// 申请释放的轮次
	const size_t Rounds = 3;
	// 每轮申请释放多少次
	const size_t N = 1000000;
	std::vector<TreeNode*> v1;
	v1.reserve(N);

	//malloc和free
	size_t begin1 = clock();
	for (size_t j = 0; j < Rounds; ++j)
	{
		for (size_t i = 0; i < N; ++i)
		{
			v1.push_back(new TreeNode);
		}
		for (size_t i = 0; i < N; ++i)
		{
			delete v1[i];
		}
		v1.clear();
	}
	size_t end1 = clock();

	//定长内存池
	ObjectPool<TreeNode> TNPool;
	std::vector<TreeNode*> v2;
	v2.reserve(N);
	size_t begin2 = clock();
	for (size_t j = 0; j < Rounds; ++j)
	{
		for (size_t i = 0; i < N; ++i)
		{
			v2.push_back(TNPool.New());
		}
		for (size_t i = 0; i < N; ++i)
		{
			TNPool.Delete(v2[i]);
		}
		v2.clear();
	}
	size_t end2 = clock();

	cout << "new cost time:" << end1 - begin1 << endl;
	cout << "object pool cost time:" << end2 - begin2 << endl;
}

//多线程malloc&free测试
void BenchmarkMalloc(size_t ntimes, size_t nworks, size_t rounds) {
	std::vector<std::thread> vthread<nworks>;
	std::atomic<size_t> malloc_costtime = 0;
	std::atomic<size_t> free_costtime = 0;
	
	for (size_t i = 0; i < nworks; i++) {
		vthread[i] = std::thread([&,k]() {
				std::vector<void*> v;
				v.reserve(ntimes);
				for (size_t j = 0; j < rounds; j++) {
					//内存申请
					size_t begin1 = clock();
					for (size_t k = 0; k < ntimes; k++) {
						v.push_back(malloc(16));
					}
					size_t end1 = clock();
					//内存释放
					size_t begin2 = clock();
					for (size_t k = 0; k < ntimes; k++) {
						free(v[k]);
					}
					size_t end2 = clock();
					v.clear();
					malloc_costtime += begin1 - end1;
					free_costtime += begin2 - end2;
				}
		});
	}

	for (auto& t : vthread) {
		t.join();
	}
	
	printf("%u个线程并发执行%u轮，每轮malloc%u次，花费时间%u ms\n",
			nworks, rounds, ntimes, malloc_costtime);
	printf("%u个线程并发执行%u轮，每轮free%u次，花费时间%u ms\n",
			nworks, rounds, ntimes, free_costtime);
	printf("%u个线程并发执行malloc&free %u次，共花费%u ms\n",
			nworks, nworks*rounds*ntimes, malloc_costtime + free_costtime);
}

//多线程ConcurrentAlloc&Free测试
void BenchmarkConcurrentAlloc(size_t ntimes, size_t nworks, size_t rounds) {
	std::vector<std::thread> vthread<nworks>;
	std::atomic<size_t> malloc_costtime = 0;
	std::atomic<size_t> free_costtime = 0;
	
	for (size_t i = 0; i < nworks; i++) {
		vthread[i] = std::thread([&,k]() {
				std::vector<void*> v;
				v.reserve(ntimes);
				for (size_t j = 0; j < rounds; j++) {
					//内存申请
					size_t begin1 = clock();
					for (size_t k = 0; k < ntimes; k++) {
						v.push_back(ConcurrentAlloc(16));
					}
					size_t end1 = clock();
					//内存释放
					size_t begin2 = clock();
					for (size_t k = 0; k < ntimes; k++) {
						ConcurrentFree(v[k]);
					}
					size_t end2 = clock();
					v.clear();
					malloc_costtime += begin1 - end1;
					free_costtime += begin2 - end2;
				}
		});
	}

	for (auto& t : vthread) {
		t.join();
	}
	
	printf("%u个线程并发执行%u轮，每轮concurrent alloc%u次，花费时间%u ms\n",
			nworks, rounds, ntimes, malloc_costtime);
	printf("%u个线程并发执行%u轮，每轮concurrent free%u次，花费时间%u ms\n",
			nworks, rounds, ntimes, free_costtime);
	printf("%u个线程并发执行concurrentAlloc&Free %u次，共花费%u ms\n",
			nworks, nworks*rounds*ntimes, malloc_costtime + free_costtime);
}

int main() {
	//test();
	//TestObjectPool();
	BenchmarkMalloc();
	BenchmarkConcurrentAlloc();
	
	return 0;
}
